<?php
/**
* @desc очень упрощенный пагинатор. Применется так:
*   
* В котнроллере: 
*         $paginator = new CPaginator($total, $num_for_page);
*         $this->view->vars["paginator"] = $paginator;
*         // получить номер текущей страницы можно $paginator->currentPage() 
*  
* В шаблоне:
* {foreach from="$paginator->pagelinks()" item="$item"}
*    {if test="$item['selected']"}
*        <span><b>{$item.text}</b></span>
*    {else}
*        <span><a href="{$item.link}">{$item.text}</a></span>
*    {/if}
* {/foreach} 
*/


class CPaginator{
    private $current_page = 1;
    private $page_key;
    private $page_links = array();
    private $window_size;
    private $root_dir;
    private $page_pattern;
    
    private $num_for_page, $total;
    private $page_count = 0;
    private $has_invisible_prev = false;
    private $has_invisible_next = false;
    
    const MIDDLE = 5;
    
    
    function __construct($total, $num_for_page, $window_size = 10, $page_key = "p", $root_dir = false, $page_pattern = false){
        if(!$num_for_page) throw new Exception("num_for_page не может быть нулём");
        $this->total = $total;
        $this->window_size = $window_size;
        $this->num_for_page = $num_for_page;
        $this->page_key = $page_key;
        $this->root_dir = $root_dir;
        $this->page_pattern = $page_pattern;
        $this->makePageLinks();
    }
    
    public function makePagelinks($current_page = false){
        if($current_page === false)
            $this->current_page = empty($_GET[$this->page_key]) ? 1 : strip_tags($_GET[$this->page_key]) + 0;
        else
            $this->current_page = $current_page;
        $this->page_count = ceil($this->total / $this->num_for_page);

        $num_of_pages = ceil($this->total/$this->num_for_page);
        if($num_of_pages == 1) return array(); //если все влазиет на одну страницу, то пагинация вообще не нужна
        $ret = array();
        $MIDDLE = 5;
        
        //вычисление границ "окна"
        $start = $this->current_page > floor($this->window_size/2) ? ($this->current_page - floor($this->window_size/2))+1 : 1;
        $window_end = $start + $this->window_size - 1;
        $end = min($window_end, $num_of_pages);
        
        //определение, существуют ли скрытые страницы
        if($start > 1) $this->has_invisible_prev = true;        
        if($end < $num_of_pages) $this->has_invisible_next = true;        
        
        for($i = $start; $i <= $end; $i++){
            $pagelink = array();
            $pagelink["text"] = $i."";
            $get_variables = $_GET;
            $get_variables[$this->page_key] = $i;
            $pagelink["index"] = $i;
            if($this->root_dir)
            {
                if($this->page_pattern)
                	$pagelink["link"] = str_replace($this->page_pattern,$this->page_key.$i,$this->root_dir);
                else
                	$pagelink["link"] = $this->root_dir."/".$this->page_key.$i."/";
			}
            else
                $pagelink["link"] = "?".$this->makeQueryString($get_variables);
            $pagelink["selected"] = ($this->current_page == $i);
            $ret[] = $pagelink;
        }
        $this->page_links = $ret;
    }
    
    /**
    * @desc возвращает массив array(array('text' => '1', 'link' => '?p=1', 'selected' = false),...)
    */
    public function pagelinks(){
        return $this->page_links;
    }
    
    
    private function makeQueryString($get_array){
    	$query = http_build_query($get_array);
        $query = str_replace("=&", "&", $query);
        return $query;
    }
    
    public function currentPage(){
        return $this->current_page;
    }

    public function setCurrentPage($value){
        $this->makePagelinks($value);
    }
    
    public function pageCount(){
        return $this->page_count;
    }
    
    public function hasInvisiblePrev(){return $this->has_invisible_prev;}
    public function hasInvisibleNext(){return $this->has_invisible_next;}
    public function getWindowSize(){
        return $this->window_size;
    }
    
    public function getFirstPageLink(){
        $get_variables = $_GET;
        $get_variables[$this->page_key] = 1;
        if($this->root_dir) 
        {
        	if($this->page_pattern)
        		return str_replace($this->page_pattern,$this->page_key."1",$this->root_dir);
	        else
        		return $this->root_dir."/".$this->page_key."1/";
		}
        return "?".$this->makeQueryString($get_variables);
    }

    public function getLastPageLink(){
        $get_variables = $_GET;
        $get_variables[$this->page_key] = $this->page_count;
        if($this->root_dir) 
        {
        	if($this->page_pattern)
        		return str_replace($this->page_pattern,$this->page_key.$this->page_count,$this->root_dir);
        	else
        		return $this->root_dir."/".$this->page_key.$this->page_count."/";
		}
        return "?".$this->makeQueryString($get_variables);
    }

    public function getPrevPageLink(){
        $get_variables = $_GET;
        $page_to = ($this->current_page == 1) ? 1 : $this->current_page - 1;
        $get_variables[$this->page_key] = $page_to;
        if($this->root_dir) 
        {
        	if($this->page_pattern)
        		return str_replace($this->page_pattern,$this->page_key.$page_to,$this->root_dir);
        	else
        		return $this->root_dir."/".$this->page_key.$page_to."/";
		}
        return "?".$this->makeQueryString($get_variables);
    }

    public function getNextPageLink(){
        $get_variables = $_GET;
        $page_to = ($this->current_page == $this->page_count) ? $this->page_count : $this->current_page + 1;
        $get_variables[$this->page_key] = $page_to;
        if($this->root_dir) 
        {
        	if($this->page_pattern)
        		return str_replace($this->page_pattern,$this->page_key.$page_to,$this->root_dir);
        	else
        		return $this->root_dir."/".$this->page_key.$page_to."/";
		}
        return "?".$this->makeQueryString($get_variables);
    }

    public function getPrevFrameLink(){
        $get_variables = $_GET;
        $page_to = $this->current_page - $this->window_size;
        if($page_to < 1) $page_to = 1;
        $get_variables[$this->page_key] = $page_to;
        if($this->root_dir) 
        {
        	if($this->page_pattern)
        	    return str_replace($this->page_pattern,$this->page_key.$page_to,$this->root_dir);
        	else
        		return $this->root_dir."/".$this->page_key.$page_to."/";
		}
        return "?".$this->makeQueryString($get_variables);
    }

    public function getNextFrameLink(){
        $get_variables = $_GET;
        $page_to = $this->current_page + $this->window_size;
        if($page_to > $this->page_count) $page_to = $this->page_count;
        $get_variables[$this->page_key] = $page_to;
        if($this->root_dir) 
        {
        	if($this->page_pattern)
        	    return str_replace($this->page_pattern,$this->page_key.$page_to,$this->root_dir);
        	else
        		return $this->root_dir."/".$this->page_key.$page_to."/";
		}
        return "?".$this->makeQueryString($get_variables);
    }
    
    public function isPageFirst(){
        return ($this->currentPage() == 1);
    }

    public function isPageLast(){
        return ($this->currentPage() == $this->page_count);
    }
    
    public function getOffset(){
    	return ($this->currentPage()-1)*$this->num_for_page;
	}
}
?>
